#ifndef JBUFFER
#define JBUFFER

#include <JXQIO/JAbstractIO>

namespace JXQ
{

class JDebug;
class JBufferPrivate;

// 内存缓冲，读写方式与读写文件一样
// 读取数据不会清除缓存，如果需要则手动清除
class JXQLIB_EXPORT JBuffer : public JAbstractIO
{
public:
	explicit JBuffer(int64_t bufSize = 4096);
	JBuffer(const void *initData, int64_t size, int64_t bufSize = 4096);
	~JBuffer();

public:
	bool close() override;

public:
	void setBufferSize(int64_t size) override;
	int64_t bytesAvailable() const override; //size
	int64_t size() const override; //缓存总大小

public:
	void clear();
	void flush() override; //clear

public:
	int64_t seek(SeekWhence whence, int64_t offset) override;
	int64_t tell() const override;

public:
	const char *data() const;
	char &operator[](int64_t index);

protected:
	int64_t virtualRead(int64_t bufSize, void *buffer) override;
	int64_t virtualWrite(int64_t bufSize, const void *buffer) override;

protected:
	explicit JBuffer(JBufferPrivate *d_ptr);
	JBuffer(JBufferPrivate *d_ptr, const void *initData, int64_t size);

private:
	J_DECLARE_PRIVATE(JBuffer)
	J_DISABLE_COPY(JBuffer)

private:
	friend JDebug &operator<<(JDebug &d, const JBuffer *jbuffer);
	friend JDebug &operator<<(JDebug &&d, const JBuffer *jbuffer);
	friend JDebug &operator<<(JDebug &d, const JBuffer &jbuffer);
	friend JDebug &operator<<(JDebug &&d, const JBuffer &jbuffer);
};

class JQueueBufferPrivate;

// 环形队列缓冲
// 读取数据会清除对应的缓存（节点出队）
class JXQLIB_EXPORT JQueueBuffer : public JBuffer
{
public:
	explicit JQueueBuffer(int64_t bufSize = 4096);
	JQueueBuffer(const void *initData, int64_t size, int64_t bufSize = 4096);

public:
	void setBufferSize(int64_t size) override;
	int64_t bytesAvailable() const override; //队列实际长度

public:
	// 直接读取数据会使数据出队，有些时候需要访问数据但不希望数据出队
	int64_t preread(void *buffer, int64_t bufSize);
	JString preread();

	int64_t find(char c = '\n') const;
	int64_t rfind(char c = '\n') const;

public:
	void flush() override; //clear
	int64_t tell() const override;

public:
	int64_t bytesWritable() const;
	bool isFull() const;
	bool isEmpty() const;

protected:
	int64_t virtualRead(int64_t bufSize, void *buffer) override;
	int64_t virtualWrite(int64_t bufSize, const void *buffer) override;
	inline int64_t seek(SeekWhence whence, int64_t offset) override { return 0; }

private:
	J_DECLARE_PRIVATE(JQueueBuffer)
	J_DISABLE_COPY(JQueueBuffer)

private:
	friend JDebug &operator<<(JDebug &d, const JQueueBuffer *jbuffer);
	friend JDebug &operator<<(JDebug &&d, const JQueueBuffer *jbuffer);
	friend JDebug &operator<<(JDebug &d, const JQueueBuffer &jbuffer);
	friend JDebug &operator<<(JDebug &&d, const JQueueBuffer &jbuffer);
};

inline int64_t JBuffer::bytesAvailable() const
{
	return size();
}

inline void JBuffer::clear()
{
	flush();
}

inline int64_t JQueueBuffer::tell() const
{
	return bytesAvailable();
}

} //namespace JXQ


#endif //JBUFFER
